home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Leser 15 / Amiga Plus Leser CD 15.iso / Tools / Development / MosaicSRC / libwww2 / HTTelnet.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-03-13  |  9.9 KB  |  493 lines

  1. /*        Telnet Acees, Roligin, etc            HTAccess.c
  2. **        ==========================
  3. **
  4. ** Authors
  5. **    TBL    Tim Berners-Lee timbl@info.cern.ch
  6. **    JFG    Jean-Francois Groff jgh@next.com
  7. **    DD    Denis DeLaRoca (310) 825-4580  <CSP1DWD@mvs.oac.ucla.edu>
  8. ** History
  9. **     8 Jun 92 Telnet hopping prohibited as telnet is not secure (TBL)
  10. **    26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. (JFG)
  11. **     6 Oct 92 Moved HTClientHost and logfile into here. (TBL)
  12. **    17 Dec 92 Tn3270 added, bug fix. (DD)
  13. **     2 Feb 93 Split from HTAccess.c. Registration.(TBL)
  14. */
  15.  
  16. /* Implements:
  17. */
  18. #include "HTTelnet.h"
  19.  
  20. #include "HTParse.h"
  21. #include "HTUtils.h"
  22. #include "HTAnchor.h"
  23. #include "HTTP.h"
  24. #include "HTFile.h"
  25. #include <errno.h>
  26. #include <stdio.h>
  27.  
  28. #include "tcp.h"
  29. #include "HText.h"
  30.  
  31. #include "HTAccess.h"
  32. #include "HTAlert.h"
  33.  
  34. #ifdef _AMIGA
  35. #include <dos/dos.h>
  36. #include <dos/dostags.h>
  37. #include <proto/dos.h>
  38. #endif
  39. extern void application_user_feedback (char *);
  40.  
  41.  
  42. #ifndef _AMIGA
  43. /*    make a string secure for passage to the
  44. **    system() command.  Make it contain only alphanumneric
  45. **    characters, or the characters '.', '-', '_', '+'.
  46. **    Also remove leading '-' or '+'.
  47. **    -----------------------------------------------------
  48. */
  49. PRIVATE void make_system_secure ARGS1(char *, str)
  50. {
  51.     char *ptr1, *ptr2;
  52.  
  53.     if ((str == NULL)||(*str == '\0'))
  54.     {
  55.         return;
  56.     }
  57.  
  58.     /*
  59.      * remove leading '-' or '+' by making it into whitespace that
  60.      * will be stripped later.
  61.      */
  62.     if ((*str == '-')||(*str == '+'))
  63.     {
  64.         *str = ' ';
  65.     }
  66.  
  67.     ptr1 = ptr2 = str;
  68.  
  69.     while (*ptr1 != '\0')
  70.     {
  71.         if ((!isalpha((int)*ptr1))&&(!isdigit((int)*ptr1))&&
  72.             (*ptr1 != '.')&&(*ptr1 != '_')&&
  73.             (*ptr1 != '+')&&(*ptr1 != '-'))
  74.         {
  75.             ptr1++;
  76.         }
  77.         else
  78.         {
  79.             *ptr2 = *ptr1;
  80.             ptr2++;
  81.             ptr1++;
  82.         }
  83.     }
  84.     *ptr2 = *ptr1;
  85. }
  86.  
  87. PRIVATE void run_a_command ARGS1(char *, command)
  88. {
  89.     char **argv;
  90.     int argc;
  91.     char *str;
  92.     int alen;
  93.  
  94.     alen = 10;
  95.     argv = (char **)malloc(10 * sizeof(char *));
  96.     if (argv == NULL)
  97.     {
  98.         return;
  99.     }
  100.     argc = 0;
  101.  
  102.     str = strtok(command, " \t\n");
  103.     while (str != NULL)
  104.     {
  105.         argv[argc] = strdup(str);
  106.         argc++;
  107.         if (argc >= alen)
  108.         {
  109.             int i;
  110.             char **tmp_av;
  111.  
  112.             tmp_av = (char **)malloc((alen + 10) * sizeof(char *));
  113.             if (tmp_av == NULL)
  114.             {
  115.                 return;
  116.             }
  117.             for (i=0; i<alen; i++)
  118.             {
  119.                 tmp_av[i] = argv[i];
  120.             }
  121.             alen += 10;
  122.             free((char *)argv);
  123.             argv = tmp_av;
  124.         }
  125.         str = strtok(NULL, " \t\n");
  126.     }
  127.     argv[argc] = NULL;
  128.  
  129.     if (fork() == 0)
  130.     {
  131.         execvp(argv[0], argv);
  132.     }
  133.     else
  134.     {
  135.         int i;
  136.  
  137.         /*
  138.          * The signal handler in main.c will clean this child
  139.          * up when it exits.
  140.          */
  141.  
  142.         for (i=0; i<argc; i++)
  143.         {
  144.             if (argv[i] != NULL)
  145.             {
  146.                 free(argv[i]);
  147.             }
  148.         }
  149.         free((char *)argv);
  150.     }
  151. }
  152. #endif
  153.  
  154. /*    Telnet or "rlogin" access
  155. **    -------------------------
  156. */
  157. PRIVATE int remote_session ARGS2(char *, access, char *, host)
  158. {
  159.   char *user, *hostname, *port;
  160.   int portnum;
  161.   char command[256];
  162.   char *xterm_str;
  163.   enum _login_protocol { telnet, rlogin, tn3270 } login_protocol;
  164.   extern char *global_xterm_str;
  165. #ifdef          _AMIGA
  166.   /* FIXME: remote_session doesn't do tn3270 properly for Amiga */
  167.   BPTR seglist;
  168.   extern char *amiga_telnet;
  169.   extern char *amiga_rlogin;
  170.   extern void application_user_feedback (char *);
  171. #endif
  172.  
  173.   if (!access || !host)
  174.     {
  175.       application_user_feedback
  176.     ("Cannot open remote session, because\nURL is malformed.\0");
  177.       return HT_NO_DATA;
  178.     }
  179.  
  180.   login_protocol =
  181.     strcmp(access, "rlogin") == 0 ? rlogin :
  182.       strcmp(access, "tn3270") == 0 ? tn3270 :
  183.     telnet;
  184.  
  185.   /* Make sure we won't overrun the size of command with a huge host string */
  186.   if (strlen(host) > 200)
  187.     {
  188.     host[200] = '\0';
  189.     }
  190.  
  191.   user = host;
  192.   hostname = strchr(host, '@');
  193.   port = strchr(host, ':');
  194.  
  195.   if (hostname)
  196.     {
  197.       *hostname++ = 0;    /* Split */
  198.     }
  199.   else
  200.     {
  201.       hostname = host;
  202.       user = 0;     /* No user specified */
  203.     }
  204.   if (port)
  205.     {
  206.       *port++ = 0;    /* Split */
  207.       portnum = atoi(port);
  208.     }
  209.  
  210. #ifndef _AMIGA
  211.   /*
  212.    * Make user and hostname secure by removing leading '-' or '+'.
  213.    * and allowing only alphanumeric, '.', '_', '+', and '-'.
  214.    */
  215.   make_system_secure(user);
  216.   make_system_secure(hostname);
  217.  
  218.   xterm_str = global_xterm_str;
  219.  
  220.   if (login_protocol == rlogin)
  221.     {
  222.       /* For rlogin, we should use -l user. */
  223.       if ((port)&&(portnum > 0)&&(portnum < 63336))
  224.     {
  225.       sprintf(command, "%s -e %s %s %d %s %s", xterm_str, access,
  226.           hostname,
  227.           portnum,
  228.           user ? "-l" : "",
  229.           user ? user : "");
  230.     }
  231.       else
  232.     {
  233.       sprintf(command, "%s -e %s %s %s %s", xterm_str, access,
  234.           hostname,
  235.           user ? "-l" : "",
  236.           user ? user : "");
  237.     }
  238.     }
  239.   else
  240.     {
  241.       /* For telnet, -l isn't safe to use at all -- most platforms
  242.      don't understand it. */
  243.       if ((port)&&(portnum > 0)&&(portnum < 63336))
  244.     {
  245.       sprintf(command, "%s -e %s %s %d", xterm_str, access,
  246.           hostname, portnum);
  247.     }
  248.       else
  249.     {
  250.       sprintf(command, "%s -e %s %s", xterm_str, access,
  251.           hostname);
  252.     }
  253.     }
  254.  
  255.   if (TRACE) fprintf(stderr, "HTaccess: Command is: %s\n", command);
  256.   run_a_command(command);
  257. #else /* Amiga */
  258. #ifdef _AS225
  259.   if (port && (portnum <= 0 || portnum > 63336))
  260.     port = NULL;
  261.  
  262.   if (login_protocol == rlogin)
  263.   {
  264.     if (amiga_rlogin && *amiga_rlogin)
  265.         xterm_str = amiga_rlogin;
  266.     else
  267.         xterm_str = "inet:c/rlogin";
  268.     /* doesn't allow port specification right now... */
  269.     sprintf (command, "%s %s HOST %s",
  270.         user ? "user" : "",
  271.         user ?    user  : "",
  272.         hostname);
  273.   }
  274.   else
  275.   {
  276.     if (amiga_telnet && *amiga_telnet)
  277.         xterm_str = amiga_telnet;
  278.     else
  279.         xterm_str = "inet:c/telnet";
  280.     sprintf (command, "%s %s",
  281.         hostname,
  282.         port ? port : "");
  283.   }
  284.  
  285.   if (TRACE)
  286.   {
  287.     fprintf (stderr, "HTTelnet: command is '%s', arguments are '%s'\n", xterm_str, command);
  288.   }
  289.  
  290.   if (seglist = NewLoadSegTags (xterm_str, TAG_DONE))
  291.   {
  292.     struct Process
  293.         *proc;
  294.  
  295.     if (TRACE)
  296.     {
  297.         fprintf (stderr, "HTTelnet: got seglist for %s\n", xterm_str);
  298.     }
  299.     proc =    CreateNewProcTags (
  300.                NP_Seglist,       seglist,
  301.                NP_FreeSeglist, TRUE,
  302.                NP_Name,       "Mosaic Remote Session",
  303.                NP_Cli,       TRUE,
  304.                NP_StackSize,   32000,
  305.                NP_CommandName, xterm_str,
  306.                NP_Arguments,   command,
  307.                TAG_DONE);
  308.     if (TRACE)
  309.     {
  310.         if (proc)
  311.             fprintf (stderr, "HTTelnet: new process is 0x%lx\n", (long) proc);
  312.         else
  313.             fprintf (stderr, "HTTelnet: CreateNewProc() failed. IoErr %ld\n", IoErr ());
  314.     }
  315.  
  316.     if (!proc)
  317.     {
  318.         static const char
  319.             msg_fmt [] = "Could not start '%s %s'";
  320.         char
  321.             *buf = malloc (strlen (msg_fmt) + strlen (xterm_str) + strlen (command) + 8);
  322.  
  323.         if (buf)
  324.         {
  325.             sprintf (buf, msg_fmt, xterm_str, command);
  326.             application_user_feedback (buf);
  327.             free (buf);
  328.         }
  329.     }
  330.   }
  331.   else
  332.   {
  333.     static const char
  334.         msg_fmt [] = "Could not load '%s'";
  335.     char
  336.         *buf = malloc (strlen (msg_fmt) + strlen (xterm_str) + 8);
  337.  
  338.     if (buf)
  339.     {
  340.         sprintf (buf, msg_fmt, xterm_str);
  341.         application_user_feedback (buf);
  342.         free (buf);
  343.     }
  344.   }
  345. #else /* AmiTCP */
  346.   if (port && (portnum < 0 || 63336 < portnum))
  347.     port = NULL;
  348.  
  349.   xterm_str = "amitcp:bin/napsaterm";
  350.   command [0] = 0;
  351.  
  352.   if (login_protocol == rlogin)
  353.   {
  354.     if (amiga_rlogin && *amiga_rlogin)
  355.     {
  356.         xterm_str = amiga_rlogin;
  357.         sprintf (command, "%s %s HOST %s",
  358.             user ? "user" : "",
  359.             user ?  user  : "",
  360.             hostname);
  361.     }
  362.   }
  363.   else
  364.   {
  365.     if (amiga_telnet && *amiga_telnet)
  366.     {
  367.         xterm_str = amiga_telnet;
  368.         sprintf (command, "%s %s",
  369.             hostname,
  370.             port ? port : "");
  371.     }
  372.   }
  373.  
  374.   if (command [0] == 0)
  375.   {
  376.     /* Arguments only in command, to avoid security problems */
  377.     sprintf (command, "-S Mosaic -d %s %s %s %s %s %s\n",
  378.         login_protocol == rlogin ? "NET" : "TELNET",
  379.         user ? "-r" : "",
  380.         user ? user : "",
  381.         port ? "-s" : "",
  382.         port ? port : "",
  383.         hostname);
  384.   }
  385.  
  386.   seglist = NewLoadSegTags (xterm_str, TAG_DONE) ;
  387.   if (seglist)
  388.   {
  389.     struct Process
  390.         *proc;
  391.  
  392.     proc = CreateNewProcTags (NP_Seglist, seglist,
  393.                  NP_FreeSeglist, TRUE,
  394.                  NP_Name, "Mosaic Remote Session",
  395.                  NP_Cli, TRUE,
  396.                  NP_CommandName, xterm_str,
  397.                  NP_Arguments, command,
  398.                  TAG_DONE);
  399.     if (!proc)
  400.     {
  401.         static const char
  402.             msg_fmt [] = "Could not start '%s %s'";
  403.         char
  404.             *buf = malloc (strlen (msg_fmt) + strlen (xterm_str) + strlen (command) + 8);
  405.  
  406.         if (buf)
  407.         {
  408.             sprintf (buf, msg_fmt, xterm_str, command);
  409.             application_user_feedback (buf);
  410.             free (buf);
  411.         }
  412.     }
  413.   }
  414.   else
  415.   {
  416.     static const char
  417.         msg_fmt [] = "Could not load '%s'";
  418.     char
  419.         *buf = malloc (strlen (msg_fmt) + strlen (xterm_str) + 8);
  420.  
  421.     if (buf)
  422.     {
  423.         sprintf (buf, msg_fmt, xterm_str);
  424.         application_user_feedback (buf);
  425.         free (buf);
  426.     }
  427.   }
  428. #endif /* AmiTCP */
  429. #endif /* Amiga */
  430.  
  431.   /* No need for application feedback if we're rlogging directly
  432.      in... */
  433.   if (user && login_protocol != rlogin)
  434.     {
  435.       char str[200];
  436.       /* Sleep to let the xterm get up first.
  437.      Otherwise, the popup will get buried. */
  438.       sleep (2);
  439.       sprintf (str, "When you are connected, log in as '%s'.\0", user);
  440.       application_user_feedback (str);
  441.     }
  442.  
  443.   return HT_NO_DATA;        /* Ok - it was done but no data */
  444. }
  445.  
  446. /*    "Load a document" -- establishes a session
  447. **    ------------------------------------------
  448. **
  449. ** On entry,
  450. **    addr        must point to the fully qualified hypertext reference.
  451. **
  452. ** On exit,
  453. **    returns     <0    Error has occured.
  454. **            >=0    Value of file descriptor or socket to be used
  455. **                 to read data.
  456. **    *pFormat    Set to the format of the file, if known.
  457. **            (See WWW.h)
  458. **
  459. */
  460. PRIVATE int HTLoadTelnet
  461. ARGS4
  462. (
  463.  CONST char *,        addr,
  464.  HTParentAnchor *,    anchor,
  465.  HTFormat,        format_out,
  466.  HTStream *,        sink            /* Ignored */
  467. )
  468. {
  469.     char * access;
  470.  
  471.     char * host;
  472.     int status;
  473.  
  474.     if (sink)
  475.       {
  476.     HTAlert("Can't output a live session -- it has to be interactive");
  477.     return HT_NO_ACCESS;
  478.       }
  479.     access =  HTParse(addr, "file:", PARSE_ACCESS);
  480.  
  481.     host = HTParse(addr, "", PARSE_HOST);
  482.     status = remote_session(access, host);
  483.  
  484.     free(host);
  485.     free(access);
  486.     return status;
  487. }
  488.  
  489.  
  490. PUBLIC HTProtocol HTTelnet = { "telnet", HTLoadTelnet, NULL };
  491. PUBLIC HTProtocol HTRlogin = { "rlogin", HTLoadTelnet, NULL };
  492. PUBLIC HTProtocol HTTn3270 = { "tn3270", HTLoadTelnet, NULL };
  493.